load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("@glib//gobject:gobject.bzl", "mkenums")

package(default_applicable_licenses = ["//:license"])

# library_sources, library_no_introspection_sources, library_headers,
# library_private_headers, and library_no_introspection_headers are copied from
# https://github.com/AravisProject/aravis/blob/main/src/meson.build.
LIBRARY_SOURCES = [
    "arvenums.c",
    "arvdebug.c",
    "arvsystem.c",
    "arvevaluator.c",
    "arvdomnode.c",
    "arvdomnodechildlist.c",
    "arvdomnodelist.c",
    "arvdomnamednodemap.c",
    "arvdomdocument.c",
    "arvdomdocumentfragment.c",
    "arvdomelement.c",
    "arvdomcharacterdata.c",
    "arvdomtext.c",
    "arvdomparser.c",
    "arvdomimplementation.c",
    "arvcamera.c",
    "arvgcenums.c",
    "arvgc.c",
    "arvgcnode.c",
    "arvgcpropertynode.c",
    "arvgcindexnode.c",
    "arvgcvalueindexednode.c",
    "arvgcinvalidatornode.c",
    "arvgcfeaturenode.c",
    "arvgcregisterdescriptionnode.c",
    "arvgcgroupnode.c",
    "arvgccategory.c",
    "arvgcboolean.c",
    "arvgcenumeration.c",
    "arvgcenumentry.c",
    "arvgcintegernode.c",
    "arvgcfloatnode.c",
    "arvgcregisternode.c",
    "arvgcintregnode.c",
    "arvgcstringnode.c",
    "arvgcmaskedintregnode.c",
    "arvgcfloatregnode.c",
    "arvgcstringregnode.c",
    "arvgcstructregnode.c",
    "arvgcstructentrynode.c",
    "arvgccommand.c",
    "arvgcswissknife.c",
    "arvgcswissknifenode.c",
    "arvgcintswissknifenode.c",
    "arvgcconverter.c",
    "arvgcconverternode.c",
    "arvgcintconverternode.c",
    "arvgcport.c",
    "arvgcregister.c",
    "arvgcinteger.c",
    "arvgcstring.c",
    "arvgcselector.c",
    "arvgcfloat.c",
    "arvinterface.c",
    "arvdevice.c",
    "arvstream.c",
    "arvbuffer.c",
    "arvchunkparser.c",
    "arvgvinterface.c",
    "arvgvdevice.c",
    "arvgvstream.c",
    "arvgentlsystem.c",
    "arvgentlinterface.c",
    "arvgentldevice.c",
    "arvgentlstream.c",
    "arvfakeinterface.c",
    "arvfakedevice.c",
    "arvfakestream.c",
    "arvfakecamera.c",
    "arvgvfakecamera.c",
    "arvrealtime.c",
    "arvxmlschema.c",
]

LIBRARY_NO_INTROSPECTION_SOURCES = [
    "arvmisc.c",
    "arvnetwork.c",
    "arvzip.c",
    "arvstr.c",
    "arvgvcp.c",
    "arvgvsp.c",
    "arvwakeup.c",
]

LIBRARY_HEADERS = [
    "arv.h",
    "arvtypes.h",
    "arvbuffer.h",
    "arvcamera.h",
    "arvchunkparser.h",
    "arvdebug.h",
    "arvdevice.h",
    "arvdomcharacterdata.h",
    "arvdomdocumentfragment.h",
    "arvdomdocument.h",
    "arvdomelement.h",
    "arvdomimplementation.h",
    "arvdomnamednodemap.h",
    "arvdomnode.h",
    "arvdomnodechildlist.h",
    "arvdomnodelist.h",
    "arvdomparser.h",
    "arvdomtext.h",
    "arvenums.h",
    "arvevaluator.h",
    "arvfakecamera.h",
    "arvfakedevice.h",
    "arvfakeinterface.h",
    "arvfakestream.h",
    "arvgcboolean.h",
    "arvgccategory.h",
    "arvgccommand.h",
    "arvgcconverter.h",
    "arvgcconverternode.h",
    "arvgcenumentry.h",
    "arvgcenumeration.h",
    "arvgcenums.h",
    "arvgcfeaturenode.h",
    "arvgcfloat.h",
    "arvgcfloatnode.h",
    "arvgcgroupnode.h",
    "arvgc.h",
    "arvgcindexnode.h",
    "arvgcintconverternode.h",
    "arvgcinteger.h",
    "arvgcintegernode.h",
    "arvgcinvalidatornode.h",
    "arvgcnode.h",
    "arvgcport.h",
    "arvgcpropertynode.h",
    "arvgcregisterdescriptionnode.h",
    "arvgcregister.h",
    "arvgcregisternode.h",
    "arvgcintregnode.h",
    "arvgcstringnode.h",
    "arvgcmaskedintregnode.h",
    "arvgcfloatregnode.h",
    "arvgcstringregnode.h",
    "arvgcstructregnode.h",
    "arvgcstring.h",
    "arvgcselector.h",
    "arvgcstructentrynode.h",
    "arvgcswissknife.h",
    "arvgcswissknifenode.h",
    "arvgcintswissknifenode.h",
    "arvgcvalueindexednode.h",
    "arvgvdevice.h",
    "arvgvfakecamera.h",
    "arvgvinterface.h",
    "arvgvstream.h",
    "arvgentlsystem.h",
    "arvgentlinterface.h",
    "arvgentldevice.h",
    "arvgentlstream.h",
    "arvinterface.h",
    "arvnetwork.h",
    "arvsystem.h",
    "arvrealtime.h",
    "arvstream.h",
    "arvxmlschema.h",
]

LIBRARY_PRIVATE_HEADERS = [
    "arvbufferprivate.h",
    "arvchunkparserprivate.h",
    "arvdebugprivate.h",
    "arvdeviceprivate.h",
    "arvfakedeviceprivate.h",
    "arvfakeinterfaceprivate.h",
    "arvfakestreamprivate.h",
    "arvgcprivate.h",
    "arvgcconverterprivate.h",
    "arvgcdefaultsprivate.h",
    "arvgcfeaturenodeprivate.h",
    "arvgcregisternodeprivate.h",
    "arvgcswissknifeprivate.h",
    "arvgvcpprivate.h",
    "arvgvdeviceprivate.h",
    "arvgvinterfaceprivate.h",
    "arvgvspprivate.h",
    "arvgvstreamprivate.h",
    "arvgentlsystemprivate.h",
    "arvgentlinterfaceprivate.h",
    "arvgentldeviceprivate.h",
    "arvgentlstreamprivate.h",
    "arvinterfaceprivate.h",
    "arvmiscprivate.h",
    "arvnetworkprivate.h",
    "arvrealtimeprivate.h",
    "arvstreamprivate.h",
    "arvwakeupprivate.h",
]

LIBRARY_NO_INTROSPECTION_HEADERS = [
    "arvmisc.h",
    "arvzip.h",
    "arvstr.h",
]

# USB support is enabled by default, replicating `if usb_dep.found()` in
# https://github.com/AravisProject/aravis/blob/main/src/meson.build
LIBRARY_SOURCES += [
    "arvuvinterface.c",
    "arvuvdevice.c",
    "arvuvstream.c",
]

LIBRARY_NO_INTROSPECTION_SOURCES += [
    "arvuvcp.c",
    "arvuvsp.c",
]

LIBRARY_HEADERS += [
    "arvuvinterface.h",
    "arvuvdevice.h",
    "arvuvstream.h",
]

LIBRARY_PRIVATE_HEADERS += [
    "arvuvcpprivate.h",
    "arvuvdeviceprivate.h",
    "arvuvinterfaceprivate.h",
    "arvuvstreamprivate.h",
    "arvuvspprivate.h",
]

[
    [
        mkenums(
            name = "%s_c" % target,
            srcs = srcs,
            out = "%s.c" % target,
            options = [
                "--fhead",
                fhead + '#include "%s.h"\n' % target + "".join(['#include "%s"\n' % s for s in srcs]),
            ],
            template = "arvenumtypes.c.template",
        ),
        mkenums(
            name = "%s_h" % target,
            srcs = srcs,
            out = "%s.h" % target,
            options = [
                "--fhead",
                "#pragma once\n\n#include <glib-object.h>\n" + fhead,
                "--vhead",
                vhead,
            ],
            template = "arvenumtypes.h.template",
        ),
    ]
    for target, srcs, fhead, vhead in [
        (
            "arvenumtypes",
            LIBRARY_HEADERS + LIBRARY_NO_INTROSPECTION_HEADERS,
            "#include <arvapi.h>\n",
            "ARV_API\n",
        ),
        ("arvenumtypesprivate", LIBRARY_PRIVATE_HEADERS, "", ""),
    ]
]

expand_template(
    name = "arvapi_h_in",
    out = "arvapi.h",
    substitutions = {
        "@ARV_API@": "extern",
    },
    template = "arvapi.h.in",
)

expand_template(
    name = "arvfeatures_h_in",
    out = "arvfeatures.h",
    substitutions = {
        "@ARAVIS_HAS_USB@": "1",
        "@ARAVIS_HAS_EVENT@": "0",
        "@ARAVIS_HAS_V4L2@": "0",
        "@ARAVIS_HAS_PACKET_SOCKET@": "1",
        "@ARAVIS_HAS_FAST_HEARTBEAT@": "0",
    },
    template = "arvfeatures.h.in",
)

expand_template(
    name = "arvparamsprivate_h_in",
    out = "arvparamsprivate.h",
    substitutions = {
        "#mesondefine ARV_GV_STREAM_NUM_BUFFERS": "#define ARV_GV_STREAM_NUM_BUFFERS 16",
    },
    template = "arvparamsprivate.h.in",
)

ARAVIS_VERSION = module_version()

[
    V_MAJOR,
    V_MINOR,
    V_MICRO,
] = ARAVIS_VERSION.split(".", 3)

expand_template(
    name = "arvversion_h_in",
    out = "arvversion.h",
    substitutions = {
        "@ARAVIS_VERSION@": ARAVIS_VERSION,
        "@ARAVIS_API_VERSION@": "0.10",
        "@ARAVIS_MAJOR_VERSION@": V_MAJOR,
        "@ARAVIS_MINOR_VERSION@": V_MINOR,
        "@ARAVIS_MICRO_VERSION@": V_MICRO,
    },
    template = "arvversion.h.in",
)

filegroup(
    name = "fake_camera_config",
    srcs = ["arv-fake-camera.xml"],
    visibility = ["//tests:__pkg__"],
)

filegroup(
    name = "aravis_private_headers",
    srcs = LIBRARY_PRIVATE_HEADERS,
    visibility = ["//:__subpackages__"],
)

REPO_ROOT = package_relative_label(":BUILD.bazel").workspace_root

INCLUDE_PREFIX = "/".join((
    REPO_ROOT if REPO_ROOT else ".",
    package_name(),
))

PUBLIC_HDRS_IN = LIBRARY_HEADERS + LIBRARY_NO_INTROSPECTION_HEADERS + [
    "arvapi.h",
    "arvenumtypes.h",
    "arvfeatures.h",
    "arvversion.h",
]

PUBLIC_HDRS_PREFIX = "include_aravis-%s.%s" % (V_MAJOR, V_MINOR)

PUBLIC_HDRS = ["/".join((PUBLIC_HDRS_PREFIX, hdr)) for hdr in PUBLIC_HDRS_IN]

[copy_file(
    name = "public_hdr_" + src,
    src = src,
    out = out,
) for (src, out) in zip(PUBLIC_HDRS_IN, PUBLIC_HDRS)]

cc_library(
    name = "aravis",
    srcs = LIBRARY_SOURCES + LIBRARY_NO_INTROSPECTION_SOURCES + [
        "GenTL_v1_5.h",
        "arvenumtypes.c",
        "arvenumtypesprivate.c",
        "arvenumtypesprivate.h",
        "arvparamsprivate.h",
        ":aravis_private_headers",
    ],
    hdrs = PUBLIC_HDRS,
    copts = [
        "-I%s" % INCLUDE_PREFIX,
        "-I$(BINDIR)/%s" % INCLUDE_PREFIX,
    ],
    implementation_deps = [
        "@libusb",
        "@libxml2",
        "@zlib",
    ],
    includes = [PUBLIC_HDRS_PREFIX],
    local_defines = [
        "ARAVIS_COMPILATION",
        "ARAVIS_DATA_DIR=\\\"/tmp/\\\"",
    ],
    visibility = ["//:__subpackages__"],
    deps = [
        "@glib//gio",
        "@glib//glib",
        "@glib//gmodule",
        "@glib//gobject",
    ],
)

[
    cc_binary(
        name = target,
        srcs = [
            "%s.c" % target.replace("-", ""),
            ":aravis_private_headers",
        ],
        copts = ["-I%s" % INCLUDE_PREFIX],
        local_defines = ["ARAVIS_COMPILATION"],
        deps = [":aravis"],
    )
    for target in [
        "arv-tool",
        "arv-camera-test",
    ]
]
